#pragma once
#include "stdafx.h"

typedef unsigned char ubyte;
typedef unsigned int uint;

const ubyte BITS_IN_BYTE=8;
const uint BITS_IN_HASH=0x100;
const ubyte BITS_IN_UBYTE=sizeof(ubyte)*BITS_IN_BYTE;
const ubyte BITS_IN_UINT=sizeof(uint)*BITS_IN_BYTE;

struct block 
{
	uint l,r;
	block(uint left=0,uint right=0):l(left),r(right){}
	void swap(){ uint temp=r;r=l;l=temp; }
	block operator^(const block x) const{
		return block(this->l^x.l,this->r^x.r);}
	block operator++(int)
	{
		block res=*this;
		const uint ALPHA=0x1010101;
		const uint BETA =0x1010104;
		const uint MAX_INT=0xFFFFFFFF;
		l+=ALPHA;
		if(r!=MAX_INT) r=(r+BETA)%MAX_INT;
		return res;
	}
	bool operator==(const block& other)
	{
		return (this->l == other.l) && (this->r == other.r);
	}
};

const uint IV_X=BITS_IN_HASH/(sizeof(block)*BITS_IN_BYTE);
struct _iv
{
	block val[IV_X];
	_iv(block x[IV_X])
	{for(ubyte i=0;i<IV_X;val[i]=x[i],++i);}

	_iv()
	{for(ubyte i=0;i<IV_X;val[i++].l=(val[i].r=0));}

	_iv operator^(const _iv x) const
	{
		block res[IV_X];
        for(ubyte i=0;i<IV_X;++i)
		{
			res[i]=val[i]^x.val[i];
		}
		return _iv(res);
	}
};
typedef _iv init_vector;
 
#include <vector>
enum MODE {ECB, CBC, CFB, TEMK, FE};
typedef std::vector<block> text;
typedef text::const_iterator ptext;
class Block_Cipher
{
public:	
	Block_Cipher(){plain=new text;cipher=new text;}
	virtual ~Block_Cipher(){delete plain;delete cipher;}

	virtual text *Encipher(const text &plain, MODE) = 0;
	virtual text *Decipher(const text &cipher, MODE) = 0;
	virtual init_vector Get_Hash(const text &plain) = 0;
protected:
	enum DIRECTION {ENCIPHER, DECIPHER};
	
	text *plain,*cipher;
	virtual block feistel(const block, ubyte iter, DIRECTION) const = 0;
	virtual uint f(const uint, const uint) const = 0;

	virtual block E(const block) = 0;
	virtual block D(const block) = 0;
};